package com.ibiz.znjd.baidu.location;

import android.os.SystemClock;

import com.baidu.location.BDLocation;
import com.baidu.location.Poi;
import com.baidu.location.PoiRegion;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.baidu.mapapi.utils.DistanceUtil;
import com.getcapacitor.JSArray;
import com.getcapacitor.JSObject;


public class LocationUtils {
    /**
     * 把百度location转换成JSON对象。
     * @param location
     * @return
     */
    public static JSObject turnToJson(BDLocation location){
        JSObject jsObject = new JSObject();
        if (null != location && location.getLocType() != BDLocation.TypeServerError) {
            // 定位类型相关信息
            if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位结果
                jsObject.put("speed", location.getSpeed());// 速度 单位：km/h
                jsObject.put("satellite", location.getSatelliteNumber());// 卫星数目
                jsObject.put("height", location.getAltitude());// 海拔高度 单位：米
                jsObject.put("gpsStatus", location.getGpsAccuracyStatus());// gps质量判断
                jsObject.put("describe", "gps定位成功");// 结果描述
                jsObject.put("isSuccess", true);
            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 网络定位结果
                // 运营商信息
                if (location.hasAltitude()) {// *****如果有海拔高度*****
                    jsObject.put("height", location.getAltitude());// 海拔高度 单位：米
                }
                jsObject.put("operationers", location.getOperators());// 运营商信息
                jsObject.put("describe", "网络定位成功");// 结果描述
                jsObject.put("isSuccess", true);
            } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {
                jsObject.put("describe", "离线定位成功，离线定位结果也是有效的");// 结果描述
                jsObject.put("isSuccess", true);
            } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                jsObject.put("describe", "网络不同导致定位失败，请检查网络是否通畅");// 结果描述
                jsObject.put("isSuccess", false);
            } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                jsObject.put("describe", "无法获取有效定位依据导致定位失败，一般是由于手机的原因，处于飞行模式下一般会造成这种结果，可以试着重启手机");// 结果描述
                jsObject.put("isSuccess", false);
            }
            /**
             * 时间也可以使用SystemClock.elapsedRealtime()方法 获取的是自从开机以来，每次回调的时间；
             * location.getTime() 是指服务端出本次结果的时间，如果位置不发生变化，则时间不变
             */
            jsObject.put("time", location.getTime());// 时间1
            jsObject.put("time2", SystemClock.elapsedRealtime());// 时间2
            jsObject.put("locType", location.getLocType());// 定位类型
            jsObject.put("latitude", location.getLatitude());// 纬度
            jsObject.put("longitude", location.getLongitude());// 经度
            jsObject.put("radius", location.getRadius());// 半径
            jsObject.put("countryCode", location.getCountryCode());// 国家码
            jsObject.put("province", location.getProvince());// 获取省份
            jsObject.put("country", location.getCountry());// 国家名称
            jsObject.put("citycode", location.getCityCode());// 城市编码
            jsObject.put("city", location.getCity());// 城市
            jsObject.put("district", location.getDistrict());// 区
            jsObject.put("town", location.getTown());// 获取镇信息
            jsObject.put("street", location.getStreet());// 街道
            jsObject.put("addr", location.getAddrStr());// 地址信息
            jsObject.put("streetNumber", location.getStreetNumber());// 获取街道号码
            jsObject.put("direction", location.getDirection());// 方向
            jsObject.put("locationdescribe", location.getLocationDescribe());// 位置语义化信息
            // POI相关信息
            if (location.getPoiList() != null && !location.getPoiList().isEmpty()) {
                JSArray pois = new JSArray();
                for (int i = 0; i < location.getPoiList().size(); i++) {
                    Poi poi = (Poi) location.getPoiList().get(i);
                    JSObject item = new JSObject();
                    item.put("poiName", poi.getName());
                    item.put("poiTag", poi.getTags());
                    pois.put(item);
                }
                jsObject.put("poi", pois);// POI信息
            }
            if (location.getPoiRegion() != null) {
                JSObject item = new JSObject();
                PoiRegion poiRegion = location.getPoiRegion();
                item.put("derectionDesc", poiRegion.getDerectionDesc()); // 获取POIREGION的位置关系，ex:"内"
                item.put("Name", poiRegion.getName()); // 获取POIREGION的名字字符串
                item.put("Tags", poiRegion.getTags()); // 获取POIREGION的类型
                jsObject.put("poiRegion", item);// 返回定位位置相对poi的位置关系，仅在开发者设置需要POI信息时才会返回，在网络不通或无法获取时有可能返回null
            }
        }else{
            jsObject.put("describe", "服务端网络定位失败，可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com，会有人追查原因");// 结果描述
            jsObject.put("isSuccess", false);
        }
        return jsObject;
    }

    /**
     * 把gcj02坐标系的转换成bd09ll坐标系
     * @param location
     * @return
     */
    public static LatLng converter(BDLocation location){
        CoordinateConverter converter  = new CoordinateConverter()
                .from(CoordinateConverter.CoordType.COMMON)
                .coord(new LatLng(location.getLatitude(),location.getLongitude()));
        LatLng desLatLng = converter.convert();
        return desLatLng;
    }

    static double DEF_PI = 3.14159265359; // PI
    static double DEF_2PI= 6.28318530712; // 2*PI
    static double DEF_PI180= 0.01745329252; // PI/180.0
    static double DEF_R =6370693.5; // radius of earth

    //适用于近距离
    public static double GetShortDistance(double lon1, double lat1, double lon2, double lat2)
    {
        double ew1, ns1, ew2, ns2;
        double dx, dy, dew;
        double distance;
        // 角度转换为弧度
        ew1 = lon1 * DEF_PI180;
        ns1 = lat1 * DEF_PI180;
        ew2 = lon2 * DEF_PI180;
        ns2 = lat2 * DEF_PI180;
        // 经度差
        dew = ew1 - ew2;
        // 若跨东经和西经180 度，进行调整
        if (dew > DEF_PI)
            dew = DEF_2PI - dew;
        else if (dew < -DEF_PI)
            dew = DEF_2PI + dew;
        dx = DEF_R * Math.cos(ns1) * dew; // 东西方向长度(在纬度圈上的投影长度)
        dy = DEF_R * (ns1 - ns2); // 南北方向长度(在经度圈上的投影长度)
        // 勾股定理求斜边长
        distance = Math.sqrt(dx * dx + dy * dy);
        return distance;
    }

    //适用于远距离
    public static double GetLongDistance(double lon1, double lat1, double lon2, double lat2)
    {
        double ew1, ns1, ew2, ns2;
        double distance;
        // 角度转换为弧度
        ew1 = lon1 * DEF_PI180;
        ns1 = lat1 * DEF_PI180;
        ew2 = lon2 * DEF_PI180;
        ns2 = lat2 * DEF_PI180;
        // 求大圆劣弧与球心所夹的角(弧度)
        distance = Math.sin(ns1) * Math.sin(ns2) + Math.cos(ns1) * Math.cos(ns2) * Math.cos(ew1 - ew2);
        // 调整到[-1..1]范围内，避免溢出
        if (distance > 1.0)
            distance = 1.0;
        else if (distance < -1.0)
            distance = -1.0;
        // 求大圆劣弧长度
        distance = DEF_R * Math.acos(distance);
        return distance;
    }

    /**
     * 计算两点之间的距离，坐标系要一致。(单位米)
     * @param lon1
     * @param lat1
     * @param lon2
     * @param lat2
     * @return
     */
    public static double getDistance(double lon1, double lat1, double lon2, double lat2){
        return DistanceUtil.getDistance(new LatLng(lat1,lon1), new LatLng(lat2, lon2));
    }

}
